package com.bee.auth.service.impl;

import com.bee.auth.common.constants.AuthRedisConst;
import com.bee.auth.common.vo.ApiVO;
import com.bee.auth.common.vo.MenuVO;
import com.bee.auth.common.vo.ResourceVO;
import com.bee.auth.manager.RoleResourceManager;
import com.bee.auth.service.AuthService;
import com.bee.commons.cache.CacheService;
import com.bee.user.client.dto.ResourceDTO;
import com.bee.user.client.enums.ResourceTypeEnum;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * @author Damin.yang
 * @date 2019/08/23 16:51
 */
@Slf4j
@Service
public class AuthServiceImpl implements AuthService {

    private static final long ROOT_PARENT = 1L;

    @Autowired
    private CacheService cacheService;
    @Autowired
    private RoleResourceManager resourceManager;

    @Override
    public void loadUserResource(Long userId, int expireTime, List<String> roles) {
        List<ResourceDTO> lists = Lists.newArrayList();
        roles.forEach(roleId -> {
            List<ResourceDTO> list = resourceManager.queryByRoleId(Long.valueOf(roleId));
            if (CollectionUtils.isNotEmpty(list)) {
                lists.addAll(list);
            }
        });

        List<ResourceVO> resourceVOS = Lists.newArrayList();
        List<ApiVO> apiVOS = Lists.newArrayList();
        List<MenuVO> menuVOS = Lists.newArrayList();

        lists.forEach(dto -> {
            if (dto.getType() == ResourceTypeEnum.API.ordinal()) {
                apiVOS.add(ApiVO.covert(dto));
            } else if (dto.getType() == ResourceTypeEnum.ELEMENT.ordinal()) {
                resourceVOS.add(ResourceVO.covert(dto));
            } else if (dto.getType() == ResourceTypeEnum.MENU.ordinal()) {
                menuVOS.add(MenuVO.covert(dto));
            }
        });

        List<MenuVO> list = getMenuVOList(menuVOS, ROOT_PARENT);

        // 放到缓存
        cacheService.set(AuthRedisConst.USER_API_PREFIX + userId, apiVOS, Long.valueOf(expireTime));
        cacheService.set(AuthRedisConst.USER_RESOURCE_PREFIX + userId, resourceVOS, Long.valueOf(expireTime));
        cacheService.set(AuthRedisConst.USER_MENU_PREFIX + userId, list, Long.valueOf(expireTime));
    }

    @Override
    public List<ApiVO> getUserApis(Long userId) {
        return (List<ApiVO>) cacheService.get(AuthRedisConst.USER_API_PREFIX + userId);
    }

    @Override
    public List<MenuVO> getUserMenus(Long userId) {
        return (List<MenuVO>) cacheService.get(AuthRedisConst.USER_MENU_PREFIX + userId);
    }

    @Override
    public List<ResourceVO> getUserResources(Long userId) {
        return (List<ResourceVO>) cacheService.get(AuthRedisConst.USER_RESOURCE_PREFIX + userId);
    }


    /**
     * 构建菜单树
     * @param menuList
     * @param parentId
     * @return
     */
    private List<MenuVO> getMenuVOList(List<MenuVO> menuList, Long parentId) {
        List<MenuVO> list = Lists.newArrayList();
        if (menuList == null) {
            return list;
        }
        for (MenuVO menuVO : menuList) {
            if (menuVO.getParentId().equals(parentId)) {
                menuVO.setSubs(getMenuVOList(menuList, menuVO.getId()));
                list.add(menuVO);
            }
        }
        Collections.sort(list, new MenuVOComparator());
        return list;
    }

    /**
     * 排序
     */
    private class MenuVOComparator implements Comparator<MenuVO> {
        @Override
        public int compare(MenuVO menu1, MenuVO menu2) {
            if(menu1 == null || menu1.getSort() == null){
                return -1;
            }
            if(menu2 == null || menu2.getSort() == null){
                return 1;
            }
            return menu1.getSort().compareTo(menu2.getSort());
        }
    }
}
